/*
 * Copyright (c) 2006-2018, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2018-01-26     armink       the first version
 */

#define LOG_TAG         "fal_flash_sfud_port"

#include <fal.h>
#include <sfud.h>

#ifdef FAL_USING_SFUD_PORT
#ifdef RT_USING_SFUD
#include <dev_spi_flash_sfud.h>
#endif

// 如果未定义 FAL_USING_NOR_FLASH_DEV_NAME，则默认使用 "norflash0" 作为 NOR Flash 设备名称
#ifndef FAL_USING_NOR_FLASH_DEV_NAME
#define FAL_USING_NOR_FLASH_DEV_NAME             "norflash0"
#endif

// 定义初始化函数，读取、写入和擦除操作的函数指针
static int init(void);
static int read(long offset, uint8_t *buf, size_t size);
static int write(long offset, const uint8_t *buf, size_t size);
static int erase(long offset, size_t size);

// 定义全局变量 sfud_dev，用于存储 SFUD 设备实例
static sfud_flash_t sfud_dev = NULL;
// 定义 NOR Flash 设备结构体 nor_flash0
struct fal_flash_dev nor_flash0 =
{
    .name       = FAL_USING_NOR_FLASH_DEV_NAME,         // 设备名称
    .addr       = 0,                                    // 设备起始地址
    .len        = 8 * 1024 * 1024,                      // 设备总长度（8MB）
    .blk_size   = 4096,                                 // 擦除块大小（4KB）
    .ops        = {init, read, write, erase},           // 操作函数指针数组
    .write_gran = 1                                     // 写入粒度
};

/**
 * 初始化 NOR Flash 设备
 * 
 * @return 成功返回 0，失败返回 -1
 */
static int init(void)
{

//#ifdef RT_USING_SFUD
//    /* RT-Thread RTOS platform */
//    sfud_dev = rt_sfud_flash_find_by_dev_name(FAL_USING_NOR_FLASH_DEV_NAME);
//#else
//    /* bare metal platform */
//    extern sfud_flash sfud_norflash0;
//    sfud_dev = &sfud_norflash0;
//#endif

//    if (NULL == sfud_dev)
//    {
//        return -1;
//    }
    // 初始化 SFUD 库
    if (SFUD_SUCCESS == sfud_init())
    {
        sfud_dev = sfud_get_device(0);
    }
    
    if (NULL == sfud_dev)
    {
        return -1;
    }
    
    
    
    /* update the flash chip information */
    nor_flash0.blk_size = sfud_dev->chip.erase_gran;
    nor_flash0.len = sfud_dev->chip.capacity;

    return 0;
}

/**
 * 从指定偏移量读取数据到缓冲区
 * 
 * @param offset 读取起始偏移量
 * @param buf 存储读取数据的缓冲区指针
 * @param size 要读取的数据长度
 * @return 返回实际读取的字节数
 */
static int read(long offset, uint8_t *buf, size_t size)
{
     // 断言 sfud_dev 已经初始化且有效
    assert(sfud_dev);
    assert(sfud_dev->init_ok);

    // 从指定偏移量读取数据到缓冲区
    sfud_read(sfud_dev, nor_flash0.addr + offset, size, buf);

    return size;
}

/**
 * 将数据写入指定偏移量
 * 
 * @param offset 写入起始偏移量
 * @param buf 要写入的数据缓冲区指针
 * @param size 要写入的数据长度
 * @return 成功返回写入的字节数，失败返回 -1
 */
static int write(long offset, const uint8_t *buf, size_t size)
{
    assert(sfud_dev);
    assert(sfud_dev->init_ok);

     // 将数据写入指定偏移量
    if (sfud_write(sfud_dev, nor_flash0.addr + offset, size, buf) != SFUD_SUCCESS)
    {
        return -1;
    }

    return size;
}


/**
 * 擦除指定偏移量开始的区域
 * 
 * @param offset 擦除起始偏移量
 * @param size 要擦除的区域长度
 * @return 成功返回擦除的字节数，失败返回 -1
 */
static int erase(long offset, size_t size)
{
    assert(sfud_dev);
    assert(sfud_dev->init_ok);

    // 擦除指定偏移量开始的区域
    if (sfud_erase(sfud_dev, nor_flash0.addr + offset, size) != SFUD_SUCCESS)
    {
        return -1;
    }

    return size;
}
#endif /* FAL_USING_SFUD_PORT */

